import { parseColorText } from '../../../common/color/color';
import { BaseComp } from '../../../common/component/comp';

import events from './events';
import { z, layouts, assets, updateAvatar, color } from './layout';
import { SeatList } from './seats';
import { HPBar } from './hpbar';
import { Tip } from './tips';

class Panel extends BaseComp {
  lastHandler = 0;
  /** @type {HTMLImageElement[]} */
  images = [];

  constructor(args) {
    super();
    this.context = args.context;
    this.zrender = args.zrender;
    this.zr = args.zr;
    this.lottery = args.lottery;

    this.x = 0;
    this.y = 0;

    this.bg = new Bg({
      parent: this,
      zrender: this.zrender,
      zr: this.zr,
    });
    this.seats = new SeatList({
      parent: this,
      zrender: this.zrender,
      zr: this.zr,
    });
    this.hpbar = new HPBar({
      parent: this,
      zrender: this.zrender,
      zr: this.zr,
    });
    this.tips = new Tip({
      parent: this,
      zrender: this.zrender,
      zr: this.zr,
    });

    this.startTick = this.startTick.bind(this);
  }

  onDanmuReceived(o) {
    //
  }

  init() {
    this.lastHandler = requestAnimationFrame(this.startTick);
  }

	startTick() {
		this._tick();
	}

  destroy() {
    super.destroy();
    cancelAnimationFrame(this.lastHandler);
  }

  tick() {
    this.lastHandler = requestAnimationFrame(this.startTick);
  }

  /**
   * 由组件通过 this.root.updateGlobalAvatar() 调用
   * @param {string} avatar 
   */
  updateGlobalAvatar(avatar) {
    updateAvatar(avatar);
    this.emit(events.AVATAR_UPDATED, avatar);
  }
}

class Bg extends BaseComp {
  spClLayers = [];
  spImgLayer;

  constructor(args) {
    super(args.parent);
    this.zrender = args.zrender;
    this.zr = args.zr;

    this.x = layouts.bg.x;
    this.y = layouts.bg.y;
  }
  
  init() {
    const [x, y] = this.absolutePos();
    const layout = layouts.bg;
    const { zrender, zr } = this;
    const spClLayer1 = new zrender.Rect({
      shape: { width: layout.width, height: layout.width }, // width == height
      style: { fill: new zrender.RadialGradient(
        0.6, 0, 0.9, [
          { offset: 0.2, color: color.dark3 },
          { offset: 0.5, color: color.gDark3 },
          { offset: 0.7, color: color.gDark2 },
          { offset: 1.0, color: color.gDark1 },
        ]
      )},
      position: [x, y],
      z: z.bg.colorLayer, zlevel: -100,
    });
    zr.add(spClLayer1);
    this.spClLayers.push(spClLayer1);
    const spClLayer2 = new zrender.Rect({
      shape: { width: layout.width, height: layout.height / 4 },
      style: { fill: new zrender.LinearGradient(
        0, 0, 0, 1, [
          { offset: 0.4, color: parseColorText(color.dark3).setA(128).toHexRGBA() },
          { offset: 1,   color: parseColorText(color.dark3).setA(0).toHexRGBA() },
        ],
      ), blend: 'darken', },
      position: [x, y],
      z: z.bg.colorLayer + 1,
    });
    zr.add(spClLayer2);
    this.spClLayers.push(spClLayer2);

    const spClLayer3 = new zrender.Rect({
      shape: { width: layout.width, height: layout.height },
      style: { fill: new zrender.LinearGradient(
        0, 0, 0, 1, [
          { offset: 0,   color: parseColorText(color.normal).setA(0).toHexRGBA() },
          { offset: 0.4, color: parseColorText(color.light1).setA(96).toHexRGBA() },
          { offset: 0.6, color: parseColorText(color.light1).setA(96).toHexRGBA() },
          { offset: 1,   color: parseColorText(color.normal).setA(0).toHexRGBA() },
        ],
      ), blend: 'lighter', },
      position: [x, y],
      z: z.bg.colorLayer + 2, zlevel: -100,
    });
    zr.add(spClLayer3);
    this.spClLayers.push(spClLayer3);

    new Promise((rs, rj) => {
      let image = document.createElement('img');
      image.onload = (e) => rs(image);
      image.onerror = (e) => rj(image);
      image.src = assets.bgTmpTintFunc(this.getContext());
    }).then(img => {
      const scale = 720 / 1080;
      const spImgLayer = this.spImgLayer = new zrender.Image({
        style: {
          image: img,
          shadowColor: color.dark1,
          shadowOffsetX: -10,
          shadowOffsetY: -3,
          shadowBlur: 8,
          blend: 'screen',
          opacity: 1,
        },
        position: [x, y + (layouts.height - img.height * scale)],
        z: z.bg.spriteLayer + 1,
        scale: [ scale, scale ]
      });
      zr.add(spImgLayer);
    });

    // canvas
    Promise.all([
      this.imagePromise(assets.bgSkyLine1Func),
      this.imagePromise(assets.bgSkyLine2Func),
      this.imagePromise(assets.bgSkyLine3Func),
      this.imagePromise(assets.bgSkyLine4Func),
      this.imagePromise(assets.bgSunlightFunc)
    ]).then(imgArray => {
      this.images = imgArray;
      this.canvas = createCanvas();
      
      const ctx2d = this.canvas.getContext('2d');
      ctx2d.fillStyle = '#111';
      ctx2d.fillRect(0, layouts.height * 0.9, layouts.width, layouts.height / 10 + 1);
      ctx2d.fillStyle = '#FFF';
    });
  }

  imagePromise(imgFunc) {
    return new Promise((rs, rj) => {
      const image = document.createElement('img');
      image.src = imgFunc(this.getContext());
      image.onload = _ => rs(image);
      image.onerror = e => rj(e);
    })
  }

  tick() {
    this.canvas && this.makeDirty();
  }

  paint() {
    if (this.canvas == null) {
      return;
    }
    
    const ctx2d = this.canvas.getContext('2d');
    ctx2d.clearRect(0, 0, layouts.width, layouts.height * 0.9);
    const now = new Date().getTime();
    const scale = 720 / 1080;

    // 图四: 5400 x 670
    this.drawBg(ctx2d, this.images[3], now, 900000, scale);
    // 图三: 4734 x 604
    this.drawBg(ctx2d, this.images[2], now, 660000, scale);
    // 图二: 4494 x 1022
    this.drawBg(ctx2d, this.images[1], now, 337000, scale);
    // 光
    this.drawBg(ctx2d, this.images[4], now, 450000, 2, 0.25);
    // 图一: 5360 x 332
    this.drawBg(ctx2d, this.images[0], now, 160000, scale);


    // this.spCanvas.dirty(); // 强制更新
  }

  /**
   * @param {CanvasRenderingContext2D} ctx2d 
   * @param {HTMLImageElement} image 
   * @param {number} now 
   * @param {number} duration 
   * @param {number} scale 
   */
  drawBg(ctx2d, image, now, duration, scale, opacity = 1) {
    const delta = (now % duration) / duration * image.width;
    // ctx2d.shadowColor = '#FFF2';
    // ctx2d.shadowBlur = 2;
    ctx2d.globalAlpha = opacity;
    ctx2d.drawImage(image, delta, 0, layouts.width / scale, image.height,
        0, layouts.height * 0.9 - scale * image.height, layouts.width, image.height * scale);
    const loop = delta + layouts.width / scale - image.width;
    if (loop > 0) {
      ctx2d.drawImage(image, 0, 0, loop, image.height,
        layouts.width - loop * scale, layouts.height * 0.9 - scale * image.height, loop * scale, image.height * scale);
    }
  }
}

function createCanvas() {
  const canvas = document.createElement('canvas');
  canvas.id = 'bg';
  canvas.style.position = 'absolute';
  canvas.style.overflow = 'hidden';
  canvas.width = layouts.width;
  canvas.height = layouts.height;
  // canvas.style.width = layouts.width + 'px';
  // canvas.style.height = layouts.height + 'px';
  canvas.style.left = '0px';
  canvas.style.top = '0px';
  canvas.style.zIndex = -1;
  canvas.style.mixBlendMode = 'soft-light';
  canvas.style.opacity = 0.5;
  const main = document.getElementById('main');
  main.appendChild(canvas);
  global.c = canvas;
  return canvas;
}

export {
  Panel
};